/**
 * @license
 * Copyright Alibaba.com All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
 */

import { ContentObserver } from '@angular/cdk/observers';
import {
  AfterViewInit,
  ChangeDetectionStrategy,
  Component,
  ElementRef,
  Input,
  OnChanges,
  OnDestroy,
  OnInit,
  Renderer2,
  SimpleChanges,
  TemplateRef,
  ViewChild,
  ViewEncapsulation
} from '@angular/core';
import { isEmpty, zoomBadgeMotion, InputBoolean } from '@shared/apes/core';
import { Subject } from 'rxjs';
import { startWith, takeUntil } from 'rxjs/operators';

export type ApesBadgeStatusType = 'success' | 'processing' | 'default' | 'error' | 'warning';

@Component({
  selector: 'apes-badge',
  exportAs: 'apesBadge',
  preserveWhitespaces: false,
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  animations: [zoomBadgeMotion],
  templateUrl: './apes-badge.component.html',
  host: {
    '[class.apes-badge-status]': 'apesStatus'
  }
})
export class ApesBadgeComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy {
  private destroy$ = new Subject();
  maxNumberArray: string[] = [];
  countArray: number[] = [];
  countSingleArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  colorArray = [
    'pink',
    'red',
    'yellow',
    'orange',
    'cyan',
    'green',
    'blue',
    'purple',
    'geekblue',
    'magenta',
    'volcano',
    'gold',
    'lime'
  ];
  presetColor: string | null = null;
  count: number;
  @ViewChild('contentElement', { static: false }) contentElement: ElementRef;
  @Input() @InputBoolean() apesShowZero = false;
  @Input() @InputBoolean() apesShowDot = true;
  @Input() @InputBoolean() apesDot = false;
  @Input() apesOverflowCount = 99;
  @Input() apesText: string;
  @Input() apesColor: string;
  @Input() apesStyle: { [key: string]: string };
  @Input() apesStatus: ApesBadgeStatusType;
  @Input() apesCount: number | TemplateRef<void>;

  checkContent(): void {
    if (isEmpty(this.contentElement.nativeElement)) {
      this.renderer.addClass(this.elementRef.nativeElement, 'apes-badge-not-a-wrapper');
    } else {
      this.renderer.removeClass(this.elementRef.nativeElement, 'apes-badge-not-a-wrapper');
    }
  }

  get showSup(): boolean {
    return (this.apesShowDot && this.apesDot) || this.count > 0 || (this.count === 0 && this.apesShowZero);
  }

  generateMaxNumberArray(): void {
    this.maxNumberArray = this.apesOverflowCount.toString().split('');
  }

  constructor(private renderer: Renderer2, private elementRef: ElementRef, private contentObserver: ContentObserver) {
    renderer.addClass(elementRef.nativeElement, 'apes-badge');
  }

  ngOnInit(): void {
    this.generateMaxNumberArray();
  }

  ngAfterViewInit(): void {
    this.contentObserver
      .observe(this.contentElement)
      .pipe(
        startWith(true),
        takeUntil(this.destroy$)
      )
      .subscribe(() => {
        this.checkContent();
      });
  }

  ngOnChanges(changes: SimpleChanges): void {
    const { apesOverflowCount, apesCount, apesColor } = changes;
    if (apesCount && !(apesCount.currentValue instanceof TemplateRef)) {
      this.count = Math.max(0, apesCount.currentValue);
      this.countArray = this.count
        .toString()
        .split('')
        .map(item => +item);
    }
    if (apesOverflowCount) {
      this.generateMaxNumberArray();
    }
    if (apesColor) {
      this.presetColor = this.colorArray.indexOf(this.apesColor) !== -1 ? this.apesColor : null;
    }
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}
